﻿using IdentityModel;
using Microsoft.IdentityModel.Tokens;
using Rw.Core.Common.Extensions;
using WH.Common.Config.Options;
using WH.Common.Web;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System;
using System.Threading.Tasks;

namespace WH.Contracts.Handler
{
    /// <summary>
    /// 
    /// </summary>
    public class JwtTokenHandler
    {
        /// <summary>
        /// 
        /// </summary>
        public static JwtTokenModel LoginModel
        {
            get
            {
                if (string.IsNullOrWhiteSpace(AccessToken))
                {
                    throw new Exception("非法用户");
                }
                else
                {
                    try
                    {
                        return JwtTokenHandler.SerializeJWT(AccessToken);
                    }
                    catch
                    {
                        throw new Exception("非法用户");
                    }
                }
            }
        }

        /// <summary>
        /// access_token
        /// </summary>
        public static string? AccessToken
        {
            get
            {
                var token = HttpContext.Current?.Request.Headers["Authorization"].ToString().Replace("Bearer ", string.Empty);
                if (string.IsNullOrWhiteSpace(token))
                {
                    token = HttpContext.Current?.Request.Headers["access_token"].ToString();
                }

                if (string.IsNullOrWhiteSpace(token) && HttpContext.Current?.Request.Method.ToUpper().Equals("GET") == true)
                {
                    token = HttpContext.Current.Request.Query["access_token"].ToString();
                }

                if (string.IsNullOrWhiteSpace(token) && HttpContext.Current?.Request.Method.ToUpper().Equals("POST") == true)
                {
                    try
                    {
                        token = HttpContext.Current.Request.Form["access_token"].ToString();
                    }
                    catch (Exception)
                    {
                        token = string.Empty;
                    }
                }
                return token;
            }
        }

        /// <summary>
        /// 生成Token
        /// </summary>
        /// <param name="jwtsettingOptions"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public static async Task<string> IssueToken(JwtsettingOptions jwtsettingOptions, JwtTokenModel model)
        {
            //生成JwtToken
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(jwtsettingOptions.Secret);

            var expiresAt = DateTime.Now.AddMinutes(jwtsettingOptions.Expires);

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                    new Claim(JwtClaimTypes.Audience,jwtsettingOptions.Audience),
                    new Claim(JwtClaimTypes.Issuer,jwtsettingOptions.Issuer),
                    new Claim(JwtClaimTypes.Id, model.UserId),
                    new Claim(JwtClaimTypes.Name,model.UserAccount),
                    new Claim(JwtClaimTypes.Role,model.RoleId),
                    new Claim(JwtClaimTypes.FamilyName,model.Name),
                    new Claim(JwtClaimTypes.PhoneNumber, model.PhoneNumber),
                    new Claim("DutyId",model.DutyId),
                    new Claim("OrganizationId",model.OrganizationId),
                    //new Claim("Industry",model.Industry.ToString()),
                    //new Claim("Scene",model.Scene.ToString()),
                    new Claim("Policy",model.Policy),
                }),
                Expires = expiresAt,
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };

            var token = tokenHandler.CreateToken(tokenDescriptor);
            var accessToken = tokenHandler.WriteToken(token);
            return await Task.FromResult(accessToken);
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="accessToken"></param>
        /// <returns></returns>
        public static JwtTokenModel SerializeJWT(string accessToken)
        {
            var result = new JwtTokenModel();

            try
            {
                var jwtHandler = new JwtSecurityTokenHandler();
                var jwtToken = jwtHandler.ReadJwtToken(accessToken);

                jwtToken.Payload.TryGetValue(JwtClaimTypes.Id, out var userId);
                jwtToken.Payload.TryGetValue(JwtClaimTypes.Name, out var userAccount);
                jwtToken.Payload.TryGetValue(JwtClaimTypes.Role, out var roleId);
                jwtToken.Payload.TryGetValue(JwtClaimTypes.FamilyName, out var name);
                jwtToken.Payload.TryGetValue(JwtClaimTypes.PhoneNumber, out var MobilePhone);
                jwtToken.Payload.TryGetValue("DutyId", out var DutyId);
                jwtToken.Payload.TryGetValue("OrganizationId", out var OrganizationId);
                jwtToken.Payload.TryGetValue("Industry", out var Industry);
                jwtToken.Payload.TryGetValue("Scene", out var Scene);
                jwtToken.Payload.TryGetValue(JwtClaimTypes.Expiration, out var Expires);
                jwtToken.Payload.TryGetValue("Policy", out var Policy);

                result.UserId = (userId ?? string.Empty).ToString() ?? "";
                result.UserAccount = (userAccount ?? string.Empty).ToString() ?? "";
                result.RoleId = (roleId ?? string.Empty).ToString() ?? "";
                result.Name = (name ?? string.Empty).ToString() ?? "";
                result.PhoneNumber = (MobilePhone ?? string.Empty).ToString() ?? "";
                result.DutyId = (DutyId ?? string.Empty).ToString() ?? "";
                result.OrganizationId = (OrganizationId ?? string.Empty).ToString() ?? "";
                //result.Industry = Industry?.ToString()?.ToEnum<IndustryEnum>() ?? IndustryEnum.Medical;
                //result.Scene = Industry?.ToString()?.ToEnum<SceneEnum>() ?? SceneEnum.Hospital;
                result.Policy = Policy?.ToString() ?? "";
            }
            catch (Exception ex)
            {
                throw;
            }

            return result;
        }

        /// <summary>
        /// 验证token
        /// </summary>
        /// <param name="jwtStr"></param>
        /// <param name="jwtsettingOptions"></param>
        /// <param name="ValidateLifetime"></param>
        /// <returns></returns>
        public static bool ValidateToken(string jwtStr, JwtsettingOptions jwtsettingOptions, bool ValidateLifetime = true)
        {
            try
            {
                var jwtHandler = new JwtSecurityTokenHandler();
                var parm = new TokenValidationParameters
                {
                    //需要跟生成Token的信息保持一致
                    ValidateIssuerSigningKey = true,//验证全局秘匙||默认True
                    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(jwtsettingOptions.Secret)),
                    ValidateIssuer = true,//验证发布者||默认True
                    ValidIssuer = jwtsettingOptions.Issuer,
                    ValidateAudience = true,//验证访问者||默认True
                    ValidAudience = jwtsettingOptions.Audience,
                    ValidateLifetime = ValidateLifetime,//验证生命周期||默认True
                    ClockSkew = TimeSpan.Zero
                };
                jwtHandler.ValidateToken(jwtStr, parm, out var validatedToken);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}